/*
 * PMap.java
 *
 * Copyright 2009 Andres Quiroz Hernandez
 *
 * This file is part of Programming5.
 * Programming5 is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Programming5 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Programming5.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package programming5.collections;

import java.util.Map;

/**
 * This extension to the Map interface is meant to provide methods to handle put and get cases that
 * require special treatment, such as collisions or null values.
 * @author Andres Quiroz Hernandez
 * @version 6.0
 */
public interface PMap<E, D> extends Map<E, D> {

    /**
     * Analogous to the get method, but if the key is not found, inserts (with the given key) and returns the 
     * given default value.
     * @param key the search key
     * @param defaultValue an initializer or default value to be associated with the key in case no value is 
     * associated with the key in the map already
     * @return map.get(key) if it is not null; otherwise, defaultValue
     */
    public D safeGet(E key, D defaultValue);

    /**
     * Analogous to the put method, but detects and avoids collisions of existing values with the given key.
     * If the given key does not collide with that of an existing value, the given value will be inserted 
     * with the given key; however, if a collision occurs, a new key that does not collide is generated with 
     * the given key generator and used to insert the given value.
     * @param key the key with which the object should be inserted
     * @param value the value to insert
     * @param keyGenerator the object used to generate alternative keys; should return different keys each time
     * generateKey is called.
     * @return the key with which the given value is actually inserted
     */
    public E safePut(E key, D value, MapKeyGenerator<E> keyGenerator);

    public Map<E, E> safePutAll(Map<? extends E, ? extends D> otherMap, MapKeyGenerator<E> keyGenerator);

    /**
     * Put method that inserts the given value with a key that is generated by the given key generator, so that
     * it doesn't have to be specified by the caller. The implementation of the method should ensure that the
     * key used does not collide with existing values.
     * @param value the value to insert
     * @param keyGenerator the object used to generate the insertion key; should return different keys each
     * time generateKey is called.
     * @return the key with which the given value is actually inserted
     */
    public E randomPut(D value, MapKeyGenerator<E> keyGenerator);

}
